#define _CRT_SECURE_NO_WARNINGS
#include"ThreadCache.h"
#include"CentralCache.h"
#include <algorithm>
// 从thread cache内存块不足时向central cache缓存获取对象
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
	//慢开始反馈调节算法
	//1.最开始不会一次向central cache一次批量要太多，因为要太多了可能用不完
	//2.如果你不要这个size大小内存需求，那么batchNum就会不断增长，直到上限
	//3.size越大，一次向central cache要的batchNum就越小
	//4.size越小，一次向central cache要的batchNum就越大
	//size_t batchNum =std::min(_freeLists[index].MaxSize(), SizeClass::NumMoveSize(size));
	size_t batchNum = min(_freeLists[index].MaxSize(), SizeClass::NumMoveSize(size));

	if (batchNum == _freeLists[index].MaxSize())
	{
		_freeLists[index].MaxSize()++;
	}
	//获取内存条得首尾
	void* start = nullptr;
	void* end = nullptr;
	size_t actralNum = CentralCache::GetInstance()->FetchRangeObj(start,end,batchNum,size);
	assert(actralNum > 0);

	if (actralNum == 1)
	{
		assert(start == end);
		return start;
	}
	else
	{
		//将头内存块弹出去给调用对象，其余的插入对应的thread cache桶
		_freeLists[index].PushRange(NextObj(start), end,actralNum-1);
		return start;
	}
}
 
void* ThreadCache::Allocate(size_t size)
{
	assert(size <= MAX_BYTES);
	//确认是几号桶
	size_t alignSize = SizeClass::RoundUp(size);
	//确认桶坐标
	size_t index = SizeClass::Index(size);
	//如果桶内内存充足，弹出内存块给对象
	if (!_freeLists[index].Empty())
	{
		return _freeLists[index].pop();
	}
	else {
		//不足是找centralcache要
		return FetchFromCentralCache(index, alignSize);
	}
}
//释放内存
void ThreadCache::Deallocate(void* ptr,size_t size)
{
	assert(ptr);
	assert(size <= MAX_BYTES);
	//找到对应的自由链表桶，对象插入进去
	int index = SizeClass::Index(size);
	_freeLists[index].push(ptr);
	//当list内内存超出申请内存块数量，去除maxsize得内存还给centralcache
	if (_freeLists[index] .Size()>=_freeLists[index].MaxSize())
	{
		ListTooLong(_freeLists[index], size);
	}
}

//释放对象时，链表太长了，回收内存到中心内存
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
	void* start = nullptr;
	void* end = nullptr;
	list.PopRange(start, end, list.MaxSize());
	CentralCache::GetInstance()->ReleaseListTospans(start, size);
}